# 这个文件包含了一系列的维护小工具

import sys
import os
import os.path
import argparse
import urllib.request
import json
from Common import *
import KeepAccountServices
import URLBackup
import Common
import logging
import sqlite3

path = os.path.abspath(__file__)
dirname, useless = os.path.split(path)
ROOT_DIR = dirname + '/'
DATA_TMP_DIR = ROOT_DIR + 'data/tmp/'
SHORT_NAME_CONF_NAME = 'short_name_templete.json'
DB_FILE_NAME = ROOT_DIR + 'data/ka.db'
BACKUP_FILE_NAME = ROOT_DIR + 'data/commit.backup'

def printUsage() :
    print(\
'''Usage: Maintain [help | Options]
Options:
rebuild:                rebuild all records from backup file.
clean:                  clean all data and backup file.
load:                   load data from .ka file.
'''
)

def load_data_from_file(args):
    ''' 加载文件中的请求
        先把文件中的所有记录转换成url
        再向服务器依次发起请求
        成功返回0，否则返回-1
    '''
    ap = argparse.ArgumentParser('load')
    ap.add_argument('--ip',         required=True, default=None, action='store', metavar='STRING', help='KeepAccount server IP address.')
    ap.add_argument('--port',       required=True, default=None, action='store', metavar='NUM', help='KeepAccount server port.')
    ap.add_argument('-f',           required=True, default=None, action='store', metavar='FILE', help='data file name.')
    args = ap.parse_args(args)

    # 把文件中的内容全部解析成请求列表
    ub = URLBackup.URLBackup()
    requests = ub.load(args.f)
    if requests == -1:
        print('parse data file error.')
        return -1
    for req in requests:
        # 根据请求的内容拼请求URL
        service_name = req[0]
        method_name = req[1]
        req_args = req[2]
        url = '/service/' + service_name + '/' + method_name
        url_args = '&'
        for arg in req_args:
            url_args += '&' + arg + '=' + urllib.parse.quote(req_args[arg])
        url += '?' + url_args[1:]
        url = 'http://' + args.ip + ':' + str(args.port) + url
        # 执行URL
        try:
            rsp = urllib.request.urlopen(url, timeout=5)
            ret = rsp.read()
            rsp.close()
            ret = json.loads(ret)
            if ret['errno'] != 0:
                print('Request failed! url: ' + url)
                exit(1)
        except Exception as e:
            print(e)
            print('request failed. url:', url)
            return -1
    return 0

def reload_all_data(args):
    '''刪除所有數據後，重建數據庫，重新加載記錄'''
    logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG)
    logger = logging.getLogger('ReloadAllData')
        
    # 删除旧的数据库文件
    print('delete data files ...')
    if os.path.exists(DB_FILE_NAME):
        os.remove(DB_FILE_NAME)
    
    # 读取创建数据库SQL文件内容
    print('recreate database ...')
    f = open(ROOT_DIR + 'sql/create.sql', encoding='utf-8')
    create_sql_content = f.read()
    f.close()
    f = open(ROOT_DIR + 'sql/add_basic_data.sql', encoding='utf-8')
    add_basic_data_sql_content = f.read()
    f.close()
        
    # 重新创建数据库
    connect = sqlite3.connect(DB_FILE_NAME)
    connect.executescript(create_sql_content)
    connect.executescript(add_basic_data_sql_content)
    connect.commit()
    connect.close()
    
    # 读取backup文件恢复数据
    print('reload all records ...')
    services = KeepAccountServices.KeepAccountServices(logger)
    if os.path.exists(BACKUP_FILE_NAME):
        f = open(BACKUP_FILE_NAME, encoding='utf-8')
        while True:
            line = f.readline()
            if line == '':
                break
            try:
                service_name, method_name, args = strToCommitReq(line)
            except:
                print('parse file error. content:', line)
                exit(1)
            ret = services.handleRequest(service_name, method_name, args)
            if ret['errno'] != Common.Error.SUCCESS:
                raise ValueError('execute failed! ret:' + json.dumps(ret) + ' error_line: ' + line)
        f.close()
    print('finished.')
    
if __name__ == '__main__':
    if len(sys.argv) < 2 \
    or sys.argv[1] in ['-h', '--help', 'help']:
        printUsage()
        if len(sys.argv) < 2 :
            exit(1)
        exit(0)

    tool_name = sys.argv[1]
    args = sys.argv[2:]
    if tool_name == 'rebuild':
        reload_all_data(args)
    elif tool_name == 'clean':
        pass
    elif tool_name == 'load':
        load_data_from_file(args)
    else:
        print('Unknown option: ' + tool_name)
        printUsage()
        exit(1)

